home *** CD-ROM | disk | FTP | other *** search
- {
- From: MARIUS ELLEN
- Subj: DOS Environment
- }
-
- Program Environment;
- {$M $1000,32776,32776 }
- { 1K stack, 32k+8 bytes heap }
- {$T- No @ Typed checking}
- {$X+ Extended function syntax}
- {$Q- No overflow checking}
- {$A+ Word align data}
- {$S+ Stack checking}
-
- uses
-
- dos,
- strings;
-
- type
-
- PJFTRec = ^TJFTRec;
- TJFTRec = record
- JFTtable : array[1..20] of byte;
- end;
-
-
- PMCBrec = ^TMCBrec;
- TMCBrec = record
- Next : char; {4d "M", of 5a "Z"}
- PSPOwner : word;
- Length : word;
- Filler : array[0..10] of byte;
- end;
-
-
- PPSPrec = ^TPSPrec;
- TPSPrec = record {ofs, length }
- INT20 :word; {00h 2 BYTEs INT 20 instruction for CP/M CALL 0
- program termination the CDh 20h
- here is often used as a signature
- for a valid PSP }
- FreeSeg :word; {02h WORD segment of first byte beyond
- memory allocated to program}
- UnUsed04:byte; {04h BYTE unused filler }
- CMPCall :byte; {05h BYTE CP/M CALL 5 service request
- (FAR JMP to 000C0h) BUG: (DOS 2+)
- PSPs created by INT 21/AH=4Bh
- point at 000BEh}
- CPMSize :word; {06h WORD CP/M compatibility--size of
- first segment for .COM files}
- CPMrem :word; {08h 2 BYTEs remainder of FAR JMP at 05h}
- INT22 :pointer; {0Ah DWORD stored INT 22 termination address}
- INT23 :pointer; {0Eh DWORD stored INT 23 control-Break addr.}
- INT24 :pointer; {12h DWORD DOS 1.1+ stored INT 24 address}
- ParPSP :word; {16h WORD segment of parent PSP}
- JFT :TJFTRec; {18h 20 BYTEs DOS 2+ Job File Table, one byte
- per file handle, FFh = closed}
- SEGEnv :word; {2Ch WORD DOS 2+ segment of environment
- for process}
- SSSP :pointer; {2Eh DWORD DOS 2+ process's SS:SP on entry
- to last INT 21 call}
- JFTCount:word; {32h WORD DOS 3+ number of entries in JFT
- (default is 20)}
- JFTPtr :pointer; {34h DWORD DOS 3+ pointer to JFT
- (default PSP:0018h)}
- PrevPSP :pointer; {38h DWORD DOS 3+ pointer to previous PSP
- (default FFFFFFFFh in 3.x)
- used by SHARE in DOS 3.3}
- UnUsed3c:byte; {3Ch BYTE apparently unused by DOS
- versions <= 6.00}
- UnUsed3d:byte; {3Dh BYTE apparently used by some versions
- of APPEND}
- NovFlag :byte; {3Eh BYTE (Novell NetWare) flag: next byte
- initialized if CEh}
- NovTask :byte; {3Fh BYTE (Novell Netware) Novell task
- number if previous byte is CEh}
- DosVers :word; {40h 2 BYTEs DOS 5+ version to return on
- INT 21/AH=30h}
- NextPSP :word; {42h WORD (MSWin3) selector of next PSP
- (PDB) in linked list. Windows
- keeps a linked list of Windows
- programs only}
- UnUsed44:pointer; {44h 4 BYTEs unused by DOS versions <= 6.00}
- WinFlag :byte; {48h BYTE (MSWindows3) bit 0 set if non-
- Windows application (WINOLDAP)}
- UnUsed49:string[6]; {49h 7 BYTEs unused by DOS versions <= 6.00}
- RETF21 :string[2]; {50h 3 BYTEs DOS 2+ service request (INT
- 21/RETF instructions)}
- UnUsed53:word; {53h 2 BYTEs unused in DOS versions <= 6.00}
- UnUsed55:string[6]; {55h 7 BYTEs unused in DOS versions <= 6.00;
- can be used to make first FCB
- into an extended FCB }
- FCB1 :string[15]; {5Ch 16 BYTEs first default FCB, filled in
- from first commandline argument
- overwrites second FCB if opened}
- FCB2 :string[15]; {6Ch 16 BYTEs second default FCB, filled in
- from second commandline
- argument, overwrites beginning
- of commandline if opened}
- UnUsed7c:pointer; {7Ch 4 BYTEs unused}
- DTAArea :string[127];{80h 128 BYTEs commandline / default DTA
- command tail is BYTE for length
- of tail, N BYTEs for the tail,
- followed by a BYTE containing
- 0Dh}
- end;
-
-
- PMCBPSPrec = ^TMCBPSPrec;
- TMCBPSPrec = record
- MCB :TMCBRec;
- PSP :TPSPRec;
- end;
-
- var
-
- MainEnvSeg:word;
- MainEnvSize:word;
-
-
- {$ifndef TryAssembler}
- {Find DOS master environment, command/4dos etc...}
- procedure GetMainEnvironment(var envseg,envsize:word);
- var R:PMCBPSPrec;
- Rrec:array[0..1] of word absolute R;
- begin
- asm
- mov ah,52h {Get First MCB, }
- int $21 {DOS Memory Control Block (MCB)}
- mov ax,es:[bx-2] {Bevind zich 2 terug}
- mov R.word[0],0 {Offset is altijd 0}
- mov R.word[2],ax {MCB:=first DOS mcb}
- end;
-
- while true do begin
- if pos(R^.mcb.next,'MZ')=0
- then halt(7); {Memory control block destroyed}
-
- if R^.mcb.PSPOwner=R^.PSP.ParPSP then begin {found}
- EnvSeg :=R^.PSP.SegEnv;
- R:=Ptr(EnvSeg-1,0);
- EnvSize:=R^.mcb.length shl 4;
- if EnvSize>32767
- then halt(10); {Environment invalid (usually >32K)}
- exit;
- end;
- if R^.mcb.next='Z'
- then halt(9); {Memory block address invalid}
- {Er moet een environment zijn!}
- R:=ptr((Rrec[1]+(R^.mcb.length)+1),0);
- end;
- end;
-
-
- {$else}
- procedure HaltIndirect(error:word);
- begin
- halt(error);
- end;
-
-
- {Find DOS master environment, command/4dos etc...}
- procedure GetMainEnvironment(var envsegP,envsizeP:word);
- assembler;
- var mcb:pointer;
- asm
- mov ah,52h {Get First MCB, }
- int $21 {DOS Memory Control Block (MCB)}
- sub bx,2
- xor dx,dx {offset altijd 0000}
- mov ax,es:[bx]
- mov mcb.word[0],dx
- mov mcb.word[2],ax {MCB:=first DOS mcb}
-
- @repeat:
- les di,mcb
- mov bl,es:[di]
- cmp bl,4dH
- je @MCBOk
- cmp bl,5aH {was het de laatste MCB}
- jne @MCBError {zo ja dan halt(9)}
- @MCBOk:
- mov ax,es:[01h] {is segment v/h prg bij deze MCB}
- cmp ax,es:[26h] {gelijk aan EnvSegment van het prg}
- je @found {zo ja dan is ie gevonden}
-
- cmp bl,5ah {is dit de laatste mcb ?}
- je @MCBMissing {!?!? MCB main env weg!?!?}
- les di,mcb {volgende MCB zit op}
- mov ax,es {oude MCB+next}
- add ax,es:[3] {+volgende}
- inc ax {+1}
- mov mcb.word[2],ax
- jmp @repeat {herhaal tot gevonden}
-
- @MCBError:
- mov al,7 {Memory control block destroyed}
- db 0a9h {skip next mov al,xx=opcode test ax,w}
- @MCBMissing:
- mov al,9 {Memory block address invalid}
- db 0a9h {kan ook environment not found zijn!}
- @SizeErr:
- mov al,10 {Environment invalid (usually >32K)}
- push ax
- call HaltIndirect
-
- @found:
- mov ax,es:[3ch] {Get segment environment}
- mov dx,es {save es}
- les di,EnvSegP {ptr van VAR parameter}
- mov es:[di],ax {Store environment segment}
- mov es,dx {rest es}
-
- dec ax {MCB van env. is 1 paragraaf terug}
- mov es,ax {Get Size van env. uit MCB}
- mov ax,es:[3] {deze is in paragrafen}
- mov cl,4 {en wordt geconverteerd}
- shl ax,cl {naar bytes..}
-
- les di,EnvSizeP {ptr van VAR parameter}
- mov es:[di],ax {Store environment size}
- cmp ax,32768 {size moet <32k}
- jae @SizeErr {anders een foutmelding}
- end;
- {$endif}
-
- {Seperate Variable and return parameters}
- function StripEnvVariable(Variable:pchar):pchar;
- const stop='='#32#0;
- begin
- While pos(Variable^,stop)=0 do inc(Variable);
- StripEnvVariable:=Variable+1;
- Variable^:=#0;
- end;
-
-
- {like bp's getenv, this time removing spaces}
- function GetMainEnv(variable:string):string;
- var MainPtr,Params:pchar;
- data:array[0..512] of char;
- begin
- MainPtr:=ptr(MainEnvSeg,0);
- StrPCopy(@variable,variable);
- StrUpper(@variable);
- StripEnvVariable(@variable);
-
- if variable[0]<>#0 then begin
- while (MainPtr^<>#0) do begin
- StrCopy(Data,MainPtr);
- Params:=StripEnvVariable(data);
- if StrComp(Data,@Variable)=0 then begin
- GetMainEnv:=StrPas(Params);
- exit;
- end;
- MainPtr:=StrEnd(MainPtr)+1;
- end;
- end;
- GetMainEnv:='';
- end;
-
-
- {like bp's EnvCount}
- function MainEnvCount:integer;
- var MainPtr:pchar;
- index:integer;
- begin
- index:=0;
- MainPtr:=ptr(MainEnvSeg,0);
- while (MainPtr^<>#0) do begin
- MainPtr:=StrEnd(MainPtr)+1;
- inc(index);
- end;
- MainEnvCount:=index;
- end;
-
-
- {like bp's EnvStr}
- function MainEnvStr(index:integer):string;
- var MainPtr:pchar;
- begin
- MainPtr:=ptr(MainEnvSeg,0);
- while (MainPtr^<>#0) do begin
- dec(index);
- if index=0 then begin
- MainEnvStr:=StrPas(MainPtr);
- exit;
- end;
- MainPtr:=StrEnd(MainPtr)+1;
- end;
- MainEnvStr:='';
- end;
-
-
- {change environment "variable", returning succes}
- function MainEnvChange(variable:string; param:string):boolean;
- var data:array[0..512] of char;
- Mem,MainPtr,EnvPtr:pchar;
- NewSize:word absolute EnvPtr;
- EnvPtrLong:^Longint absolute EnvPtr;
-
-
- procedure EnvStrCopy(src:pchar);
- begin
- if NewSize+StrLen(src)<=MainEnvSize-4
- then begin
- StrCopy(EnvPtr,Src);
- EnvPtr:=StrEnd(EnvPtr)+1;
- end
- else MainEnvChange:=false;
- end;
-
- procedure PutVariable;
- begin
- if (Variable[0]<>#0) and (param[0]<>#0) then begin
- StrCopy(Data,@variable);
- StrCat(Data,'=');
- StrCat(Data,@param);
- EnvStrCopy(Data);
- variable[0]:=#0;
- end;
- end;
-
- begin
- getmem(Mem,MainEnvSize);
- MainPtr:=ptr(MainEnvSeg,0);
- EnvPtr:=Mem;
-
- StrPCopy(@variable,variable);
- StrUpper(@variable);
- StripEnvVariable(@variable);
- StrPCopy(@param,param);
- MainEnvChange:=variable[0]<>#0;
-
- while MainPtr^<>#0 do begin
- StrCopy(Data,MainPtr);
- StripEnvVariable(data);
- if StrComp(Data,@Variable)=0
- then PutVariable
- else EnvStrCopy(MainPtr);
- MainPtr:=StrEnd(MainPtr)+1;
- end;
-
- if variable[0]<>#0
- then PutVariable;
-
- EnvPtrLong^:=0; {4 terminating zero's}
- {1 byte terminating environment}
- {2 word counting trailing strings}
- {1 byte terminating the strings}
- {. last three disables paramstr(0)}
- move(Mem^,Ptr(MainEnvSeg,0)^,NewSize+4);
- freeMem(Mem,MainEnvSize);
- end;
-
-
- var oldprmp:string;
- begin
- GetMainEnvironment(MainEnvSeg,MainEnvSize);
- memw[prefixseg:$2c]:=MainEnvSeg;
-
- oldprmp:=GetMainEnv('fprompt');
- MainEnvChange('prompt','Please type EXIT!'#13#10+'$p$g');
-
- swapvectors;
- exec(GetMainEnv('comspec'),'');
- swapvectors;
-
- MainEnvChange('prompt',oldprmp);
- end.